package main

import (
	"errors"
	"fmt"
)

type Stack struct {
	Max int
	Top int
	arr []interface{}
}

func (stack *Stack) Push(e interface{}) error {

	if stack.Top == stack.Max-1 {
		return errors.New("栈已满")
	}

	stack.Top++
	stack.arr[stack.Top] = e

	return nil
}

func (stack *Stack) Pop() (e interface{}, err error) {

	if stack.Top == -1 {
		return nil, errors.New("栈已空")
	}

	e = stack.arr[stack.Top]
	stack.Top--

	return e, nil
}

func (stack Stack) String() string {
	return fmt.Sprintf("Stack: { max = %d, top = %d }", stack.Max, stack.Top)
}

// 示例元素结构体
type Student struct {
	id       int
	name     string
	nickname string
}

// 覆盖String方法，格式化输出
func (student *Student) String() string {
	return fmt.Sprintf("{id=%d, name=%s, nickname=%s}", student.id, student.name, student.nickname)
}

func main() {

	size := 5

	students := make([]interface{}, size)

	stack := Stack{
		Max: size,
		Top: -1,
		arr: students,
	}

	fmt.Println(stack)

	s0 := &Student{0, "晁盖", "托塔天王"}
	s1 := &Student{1, "宋江", "及时雨"}
	s2 := &Student{2, "卢俊义", "玉麒麟"}
	s3 := &Student{3, "吴用", "智多星"}
	s14 := &Student{14, "武松", "行者"}
	//s10 := &Student{10, "柴进", "小旋风"}
	//s13 := &Student{13, "鲁智深", "花和尚"}
	//s22 := &Student{22, "李逵", "黑旋风"}

	// 压栈
	fmt.Println(stack.Push(s0))
	fmt.Println(stack.Push(s1))
	fmt.Println(stack.Push(s2))
	fmt.Println(stack.Push(s3))
	fmt.Println(stack.Push(s14))
	fmt.Println(stack.Push(s14))

	// 打印
	fmt.Println(stack)

	// 弹栈
	fmt.Println(stack.Pop())
	fmt.Println(stack.Pop())
	fmt.Println(stack.Pop())
	fmt.Println(stack.Pop())
	fmt.Println(stack.Pop())
	fmt.Println(stack.Pop())
}
